package com.bj58.mis.apm.server.statistics.controller;

import com.bj58.mis.apm.server.core.common.result.Page;
import com.bj58.mis.apm.server.core.common.result.ResultBean;
import com.bj58.mis.apm.server.core.mock.annotation.Mock;
import com.bj58.mis.apm.server.core.util.UnitUtil;
import com.bj58.mis.apm.server.core.util.UnitValue;
import com.bj58.mis.apm.server.statistics.dto.chart.ChartData;
import com.bj58.mis.apm.server.statistics.dto.cube.*;
import com.bj58.mis.apm.server.statistics.query.PageInfo;
import com.bj58.mis.apm.server.statistics.query.cube.CubeQuery;
import com.bj58.mis.apm.server.statistics.service.CubeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author: zhangfx
 * @create: 2018-06-19 15:22
 **/
@RestController
@RequestMapping("/cube")
@Api(tags = "Cube相关API", description = "/cube")
@Mock(path = "/cube")
public class CubeController extends BaseController<CubeService> {

    private ExecutorService executors = Executors.newCachedThreadPool();

    /**
     * 查询cube首页所有数据
     * @param projectId
     * @param startDate
     * @param endDate
     * @return
     */
    @GetMapping(path="/cubeHomeData")
    public ResultBean<CubeHomeData> queryCubeHomeData(@RequestParam(name="projectId", required = false) String projectId,
                                                 @RequestParam(name="startDate", required = true) String startDate,
                                                 @RequestParam(name="endDate", required = true) String endDate){
        Future<ResultBean<SwellRangeStatistics>> swellRangeStatisticsFuture = executors.submit(() -> swellRangeStatistics(projectId));
        Future<ResultBean<CubeStatistics>> cubeStatisticsFuture = executors.submit(() -> statistics(projectId));
        Future<ResultBean<ChartData>> top10LowestUsageColumnFuture = executors.submit(() -> top10LowestUsageColumn(projectId));
        Future<ResultBean<ChartData>> top10SwellRatioFuture = executors.submit(() -> top10SwellRatio(projectId));
        Future<ResultBean<ChartData>> top10MostUsedQueryFuture = executors.submit(() -> top10MostUsedQuery(projectId, startDate, endDate));
        Future<ResultBean<ChartData>> top10SlowQueryFuture = executors.submit(() -> top10SlowQuery(projectId, startDate, endDate));
        Future<ResultBean<ChartData>> top10SlowBuildFuture = executors.submit(() -> top10SlowBuild(projectId));
        Future<ResultBean<ChartData>> top10DataSizeFuture = executors.submit(() -> top10DataSize(projectId));
        CubeHomeData data = new CubeHomeData();
        try {
            data.setSwellRangeStatistics(swellRangeStatisticsFuture.get().getData());
            data.setStatistics(cubeStatisticsFuture.get().getData());
            data.setTop10LowestUsageColumn(top10LowestUsageColumnFuture.get().getData());
            data.setTop10SwellRatio(top10SwellRatioFuture.get().getData());
            data.setTop10MostUsedQuery(top10MostUsedQueryFuture.get().getData());
            data.setTop10SlowQuery(top10SlowQueryFuture.get().getData());
            data.setTop10SlowBuild(top10SlowBuildFuture.get().getData());
            data.setTop10DataSize(top10DataSizeFuture.get().getData());

            return ResultBean.success(data);
        } catch (Exception e) {
            logger.error("查询异常", e);
            return ResultBean.error(e);
        }

    }



    @ApiOperation(value = "查询我的Cube!", notes = "查询当前用户有权限的Cube")
    @GetMapping(path="")
    public ResultBean<Page<CubeInfo>> query(@ModelAttribute CubeQuery cubeQuery,
                                            @ModelAttribute PageInfo pageInfo){
        String currUser = getLoginUserName();
        return ResultBean.success(this.service.queryPage(currUser, cubeQuery, pageInfo));
    }

    @ApiOperation(value = "根据ID查询Cube!", notes = "根据ID查询Cube!")
    @ApiImplicitParam(name="id", value = "Cube ID", paramType = "path", required = true, dataType = "String")
    @GetMapping(path="/{id}")
    public ResultBean<CubeInfo> get(@PathVariable(name = "id") String id){
        return ResultBean.success(this.service.get(id));
    }

    @ApiOperation(value = "根据ID查询Cube的设计信息!", notes = "查询Cube的模型设计与维度参数设计数据!")
    @ApiImplicitParam(name="id", value = "Cube ID", paramType = "path", required = true, dataType = "String")
    @GetMapping(path="/{id}/design")
    public ResultBean<CubeDesign> getDesign(@PathVariable(name = "id") String id){
        return ResultBean.success(this.service.getDesign(id));
    }

    @ApiOperation(value = "Cube分区信息", notes = "查询Cube分区信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name="id", value = "Cube ID", paramType = "path", required = true, dataType = "String")
    })
    @GetMapping(path="/{id}/segments")
    public ResultBean<List<Segment>> getSegments(@PathVariable(name="id") String id){
        return ResultBean.success(this.service.getSegments(id));
    }

    @ApiOperation(value = "Cube的模型信息", notes = "根据ID查询Cube的模型信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name="id", value = "Cube ID", paramType = "path", required = true, dataType = "String")
    })
    @GetMapping(path="/{id}/model")
    public ResultBean<Model> getModel(@PathVariable(name = "id") String id){
        return ResultBean.success(this.service.getModel(id));
    }

    @ApiOperation(value = "Cube总体统计信息!", notes = "查询当前用户有权限的Cube")
    @ApiImplicitParams({
            @ApiImplicitParam(name="projectId", value = "项目ID", paramType = "query", required = false, dataType = "String")
    })
    @GetMapping(path="/statistics")
    public ResultBean<CubeStatistics> statistics(@RequestParam(name="projectId", required = false) String projectId){
        String currUser = getLoginUserName();
        return ResultBean.success(this.service.queryStatistics(currUser, projectId));
    }

    @ApiOperation(value = "纬度使用率最低TOP10!", notes = "查询当前用户有权限的Cube")
    @ApiImplicitParams({
            @ApiImplicitParam(name="projectId", value = "项目ID", paramType = "query", required = false, dataType = "String")
    })
    @GetMapping(path="/top10/lowestUsageColumn")
    public ResultBean<ChartData> top10LowestUsageColumn(@RequestParam(name="projectId", required = false) String projectId){
        String currUser = getLoginUserName();
        List<Map<String, Object>> data = this.service.queryTop10LowestUsageColumn(currUser, projectId);

        ChartData chartData = ChartData.buildChartData(data, "cubeName", new String[]{"usageRate"}, new String[]{"维度使用率"}, null, null);
        return ResultBean.success(chartData);
    }

    @ApiOperation(value = "膨胀倍数TOP10!", notes = "查询当前用户有权限的Cube")
    @ApiImplicitParams({
            @ApiImplicitParam(name="projectId", value = "项目ID", paramType = "query", required = false, dataType = "String")
    })
    @GetMapping(path="/top10/swellRatio")
    public ResultBean<ChartData> top10SwellRatio(@RequestParam(name="projectId", required = false) String projectId){
        String currUser = getLoginUserName();
        List<Map<String, Object>> data = this.service.queryTop10SwellRatio(currUser, projectId);

        ChartData chartData = ChartData.buildChartData(data, "cubeName", new String[]{"swellRatio"}, new String[]{"膨胀倍数"}, null, null);
        return ResultBean.success(chartData);
    }

    @ApiOperation(value = "查询次数TOP10!", notes = "查询当前用户有权限的Cube")
    @ApiImplicitParams({
            @ApiImplicitParam(name="projectId", value = "项目ID", paramType = "query", required = false, dataType = "String"),
            @ApiImplicitParam(name="startDate", value = "开始时间", paramType = "query", required = true, dataType = "String"),
            @ApiImplicitParam(name="endDate", value = "结束时间", paramType = "query", required = true, dataType = "String")
    })
    @GetMapping(path="/top10/mostUsedQuery")
    public ResultBean<ChartData> top10MostUsedQuery(@RequestParam(name="projectId", required = false) String projectId,
                                                              @RequestParam(name="startDate", required = true) String startDate,
                                                              @RequestParam(name="endDate", required = true) String endDate){
        String currUser = getLoginUserName();
        List<Map<String, Object>> data = this.service.queryTop10MostUsedQuery(currUser, projectId, startDate, endDate);

        ChartData chartData = ChartData.buildChartData(data, "cubeName", new String[]{"queryCount"}, new String[]{"查询次数"}, null, null);
        return ResultBean.success(chartData);
    }

    @ApiOperation(value = "慢查询TOP10!", notes = "查询当前用户有权限的Cube")
    @ApiImplicitParams({
            @ApiImplicitParam(name="projectId", value = "项目ID", paramType = "query", required = false, dataType = "String"),
            @ApiImplicitParam(name="startDate", value = "开始时间", paramType = "query", required = true, dataType = "String"),
            @ApiImplicitParam(name="endDate", value = "结束时间", paramType = "query", required = true, dataType = "String")
    })
    @GetMapping(path="/top10/slowQuery")
    public ResultBean<ChartData> top10SlowQuery(@RequestParam(name="projectId", required = false) String projectId,
                                                          @RequestParam(name="startDate", required = true) String startDate,
                                                          @RequestParam(name="endDate", required = true) String endDate){
        String currUser = getLoginUserName();
        List<Map<String, Object>> data = this.service.queryTop10SlowQuery(currUser, projectId, startDate, endDate);

        ChartData chartData = ChartData.buildChartData(data, "cubeName", new String[]{"slowQueryCount"}, new String[]{"慢查询次数"}, null, null);
        return ResultBean.success(chartData);
    }



    @ApiOperation(value = "构建时间TOP10!", notes = "查询当前用户有权限的Cube")
    @ApiImplicitParams({
            @ApiImplicitParam(name="projectId", value = "项目ID", paramType = "query", required = false, dataType = "String")
    })
    @GetMapping(path="/top10/slowBuild")
    public ResultBean<ChartData> top10SlowBuild(@RequestParam(name="projectId", required = false) String projectId){
        String currUser = getLoginUserName();
        List<Map<String, Object>> data = this.service.queryTop10SlowBuild(currUser, projectId);

        long max = ((Number)data.get(0).get("buildTime")).longValue();
        String unit = "秒";
        if(max > 60 * 60 * 10){
            unit = "时";
            data.forEach(map -> {
                map.put("buildTime", new BigDecimal(((Number)map.get("buildTime")).longValue()).divide(new BigDecimal(60*60*10), 2, BigDecimal.ROUND_HALF_UP).doubleValue());
            });
        }else if(max > 60 * 10){
            unit = "分";
            data.forEach(map -> {
                map.put("buildTime", new BigDecimal(((Number)map.get("buildTime")).longValue()).divide(new BigDecimal(60*10), 2, BigDecimal.ROUND_HALF_UP).doubleValue());
            });
        }

        ChartData chartData = ChartData.buildChartData(data, "cubeName", new String[]{"buildTime"}, new String[]{"构建时间"}, null, new String[]{unit});
        return ResultBean.success(chartData);
    }


    @ApiOperation(value = "数据量占用TOP10!", notes = "查询当前用户有权限的Cube")
    @ApiImplicitParams({
            @ApiImplicitParam(name="projectId", value = "项目ID", paramType = "query", required = false, dataType = "String")
    })
    @GetMapping(path="/top10/dataSize")
    public ResultBean<ChartData> top10DataSize(@RequestParam(name="projectId", required = false) String projectId){
        String currUser = getLoginUserName();
        List<Map<String, Object>> data = this.service.queryTop10DataSize(currUser, projectId);
        long max = 0;
        for(Map<String, Object> map : data){
            max = Math.max(max, ((BigDecimal)map.get("dataSize")).longValue());
        }
        UnitValue uv = UnitUtil.deal(max);
        for(Map<String, Object> map : data){
            map.put("dataSize", UnitUtil.dealByUnit(((BigDecimal)map.get("dataSize")).longValue(), uv.getUint()));
            map.put("unit", uv.getUint());
        }

        ChartData chartData = ChartData.buildChartData(data, "cubeName", new String[]{"dataSize"}, new String[]{"数据量"}, null, new String[]{uv.getUint()});
        return ResultBean.success(chartData);
    }


    @ApiOperation(value = "查询Cube膨胀率范围统计!", notes = "查询总体的Cube膨胀率范围统计与我的Cube膨胀率范围统计")
    @ApiImplicitParams({
            @ApiImplicitParam(name="projectId", value = "项目ID", paramType = "query", required = false, dataType = "String")
    })
    @GetMapping(path="/swellRangeStatistics")
    public ResultBean<SwellRangeStatistics> swellRangeStatistics(@RequestParam(name="projectId", required = false) String projectId){
        String currUser = getLoginUserName();
        List<Map<String, Object>> allCubeData = this.service.querySwellRangeStatistics(null, projectId);
        List<Map<String, Object>> myCubeData = this.service.querySwellRangeStatistics(currUser, projectId);

        ChartData allCubeChartData = ChartData.buildChartData(allCubeData, "swellRange", new String[]{"cubeCount"}, new String[]{"膨胀倍数"}, null, null);
        ChartData myCubeChartData = ChartData.buildChartData(myCubeData, "swellRange", new String[]{"cubeCount"}, new String[]{"膨胀倍数"}, null, null);

        return ResultBean.success(new SwellRangeStatistics(allCubeChartData, myCubeChartData));
    }
}
